﻿using CrankShaftAnalysisSystem.Controller;
using CrankShaftAnalysisSystem.SubForm;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CrankShaftAnalysisSystem
{
    public partial class FormMain : Form
    {
        FormManual formManual;
        FormSystemState formSystemState;

        FormStart formStart;
        FormInputUuid formInputUuid;
        FormPlacePart formPlacePart;
        FormFastenPart formFastenPart;
        FormMeasuring formMeasuring;
        FormComplete formComplete;
        FormOfflineHandle formOfflineHanlde;

        MeasureSystem measureSystem;

        [Description("测量数据")]
        public DataStorage DataBase { get; set; }

        public Form[] WorkingForms { get; set; }
        public int CurrentStep { get; set; } = 0;
        public string PartUuid { get; set; }

        public SafeController safe { get; private set; }

        public class WorkingSteps
        {
            public const int Start = 0;
            public const int InputId = 1;
            public const int PlacePart = 2;
            public const int FastenPart = 3;
            public const int BeginMeasure = 4;
            public const int Finish = 5;
            public const int Max = 6;
        }

        public FormMain()
        {
            InitializeComponent();
            safe = new SafeController();
            measureSystem = MeasureSystem.Instance;
            this.IsMdiContainer = true;
            this.LayoutMdi(MdiLayout.TileHorizontal);
            formManual = new FormManual();
            formOfflineHanlde = new FormOfflineHandle();
            // 操作流程窗体
            formStart = new FormStart();
            formStart.MdiParent = this;
            formStart.Parent = panelMainTop;
            formInputUuid = new FormInputUuid();
            formInputUuid.MdiParent = this;
            formInputUuid.Parent = panelMainTop;
            formSystemState = new FormSystemState();
            formPlacePart = new FormPlacePart();
            formPlacePart.MdiParent = this;
            formPlacePart.Parent = panelMainTop;
            formFastenPart = new FormFastenPart();
            formFastenPart.MdiParent = this;
            formFastenPart.Parent = panelMainTop;
            formMeasuring = new FormMeasuring();
            formMeasuring.MdiParent = this;
            formMeasuring.Parent = panelMainTop;
            formComplete = new FormComplete();
            formComplete.MdiParent = this;
            formComplete.Parent = panelMainTop;

            formSystemState.MdiParent = this;
            formSystemState.Parent = panelMainBot;
            formInputUuid.OnConfirmUuid += (uuid) =>
            {
                PartUuid = uuid;
                UpdateStep(WorkingSteps.PlacePart, 0);
            };
            formPlacePart.OnStepConfirmed += () =>
            {
                UpdateStep(WorkingSteps.FastenPart, 0);
            };
            formFastenPart.OnStepConfirmed += () =>
            {
                UpdateStep(WorkingSteps.BeginMeasure, 0);
                DataBase = new DataStorage(PartUuid);
                formMeasuring.RefreshDataViewer(DataBase.Clouds);
                // 启动测试前关闭所有手动控制表格的采集功能
                formManual.StopAllTimers();
                measureSystem.MeasureTotalPoints(DataBase);
            };
            formMeasuring.OnComplete += () =>
            {
                UpdateStep(WorkingSteps.Finish, 0);
                formComplete.DataBase = DataBase;
            };
            formComplete.OnComplete += () =>
            {
                UpdateStep(WorkingSteps.Start, 0);
                DataBase?.Dispose();
            };
            WorkingForms = new Form[6] { formStart, formInputUuid, formPlacePart, formFastenPart, formMeasuring, formComplete };

        }

        private void MenuManulControl_Click(object sender, EventArgs e)
        {
            formManual.Show();
            formManual.BringToFront();
        }

        private void MenuSystemState_Click(object sender, EventArgs e)
        {
            MenuSystemState.Checked = !MenuSystemState.Checked;
            formSystemState.Show();
            formSystemState.Visible = MenuSystemState.Checked;
            panelMainBot.Visible = MenuSystemState.Checked;
            formSystemState.WindowState = FormWindowState.Maximized;
        }

        /// <summary>
        /// 刷新工作步骤
        /// </summary>
        /// <param name="step">写入的步骤</param>
        /// <param name="inc">0-保持原样，1-加一步，-1-减一步</param>
        public void UpdateStep(int step, int inc)
        {
            CurrentStep = step;
            CurrentStep += inc;
            if (CurrentStep == WorkingSteps.Max)
                CurrentStep = WorkingSteps.Start;
            if (CurrentStep < 0)
                CurrentStep = WorkingSteps.Max - 1;
            if (WorkingForms.Length > CurrentStep)
            {
                var form = WorkingForms[CurrentStep];
                form.WindowState = FormWindowState.Maximized;
                form.Show();
                form.BringToFront();
            }

            foreach (object ob in panelQuickMenu.Controls)
            {
                if (ob is Sunny.UI.UIButton)
                {
                    Sunny.UI.UIButton button = ob as Sunny.UI.UIButton;
                    if (button.TagString == "Step")
                    {
                        if (Convert.ToInt32(button.Tag) == CurrentStep)
                            button.Enabled = true;
                        else
                            button.Enabled = false;
                    }
                }
            }
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            UpdateStep(WorkingSteps.Start, 1);
            formInputUuid.Reset();
        }

        private void FormMain_Load(object sender, EventArgs e)
        {
            UpdateStep(CurrentStep, 0);
            tmLoop.Start();
            MenuSystemState_Click(sender, e);
            measureSystem.LoadPointConfig("../../Docs/RvConfig.json");
            measureSystem.Begin();
        }

        private void btnInputID_Click(object sender, EventArgs e)
        {
        }

        private void btnPlacePart_Click(object sender, EventArgs e)
        {
        }

        private void btnFastenPart_Click(object sender, EventArgs e)
        {
        }

        private void btnBeginMeasure_Click(object sender, EventArgs e)
        {
        }

        private void btnFinish_Click(object sender, EventArgs e)
        {
        }

        private void btnAbort_Click(object sender, EventArgs e)
        {
            UpdateStep(WorkingSteps.Start, 0);
            SafeController.StopAll();
        }

        private void tmLoop_Tick(object sender, EventArgs e)
        {
            ledChangePart.State = GetButtonLightState(VirtualDevice.Mask.CHANGEPART);
            ledAutoOn.State = GetButtonLightState(VirtualDevice.Mask.AUTOON);
            ledAutoStart.State = GetButtonLightState(VirtualDevice.Mask.AUTOSTART);
            // 急停拍下，IO断开，逻辑是反的
            ledEmergency.State = GetSafetyLightState(VirtualDevice.Mask.EMERGENCY, reverse: true);
            ledFallDown.State = GetButtonLightState(VirtualDevice.Mask.FALLDOWN);
            ledManulOn.State = GetButtonLightState(VirtualDevice.Mask.MANUALON);
            ledReserved.State = GetButtonLightState(VirtualDevice.Mask.RESERVED);
            ledReset.State = GetButtonLightState(VirtualDevice.Mask.RESET);
            ledStop.State = GetButtonLightState(VirtualDevice.Mask.STOP);
            ledAutoRun.State = GetLedLightState(VirtualDevice.Mask.AUTOLED);
            ledMT2571RefFound.State = measureSystem.MT2571.Device.RefIndexFound ? Sunny.UI.UILightState.On : Sunny.UI.UILightState.Off;

            formSystemState.ledPLCState.On = measureSystem.PLC.Device.Connected;
            formSystemState.ledEasten.On = measureSystem.Easten.Device.Connected;
            formSystemState.ledSafetySensor.On = !Tools.GetBitState(measureSystem.PLC.Device.Info.SafeInfo, VirtualDevice.Mask.SAFTEY);
            formSystemState.ledMT2571Out.On = Tools.GetBitState(measureSystem.PLC.Device.Info.FeedBackInfo, VirtualDevice.Mask.PNEUMATICPOS2);
            formSystemState.ledMT2571Back.On = Tools.GetBitState(measureSystem.PLC.Device.Info.FeedBackInfo, VirtualDevice.Mask.PNEUMATICPOS3);
            formSystemState.ledPartFastened.On = Tools.GetBitState(measureSystem.PLC.Device.Info.FeedBackInfo, VirtualDevice.Mask.PNEUMATICPOS1);
            formSystemState.ledPartReleased.On = Tools.GetBitState(measureSystem.PLC.Device.Info.FeedBackInfo, VirtualDevice.Mask.PNEUMATICPOS0);
            formSystemState.ledLaser.On = Tools.GetBitState(measureSystem.PLC.Device.Info.FeedBackInfo, VirtualDevice.Mask.PARTEXIST);
            formSystemState.ledVacuum.On = Tools.GetBitState(measureSystem.PLC.Device.Info.FeedBackInfo, VirtualDevice.Mask.VACCUMM);
            formSystemState.ledSafeStop.On = SafeController.ManualStop;
            formSystemState.ledPenCompressed.On = LogicalController.PenCompressReached;
            formSystemState.lbERM2400Ang.Text = $"{measureSystem.ERM2400.Device.Angular.ToString("F2")}Deg";
            formSystemState.lbMT2571Len.Text = $"{measureSystem.MT2571.Distance.ToString("F1")}um";
            formSystemState.lbLC485Height.Text = $"{measureSystem.LC485.Height.ToString("F2")}um";

            formSystemState.lbTemp1.Text = $"{measureSystem.PLC.Device.Temperature1}度";
            formSystemState.lbTemp2.Text = $"{measureSystem.PLC.Device.Temperature2}度";
            formSystemState.lbTemp3.Text = $"{measureSystem.PLC.Device.Temperature3}度";

            if (measureSystem.PLC.Device.StateRefreshed && !safe.Initialized)
            {
                safe.Begin();
                LogicalController.Instance.Begin();
            }
        }

        private Sunny.UI.UILightState GetButtonLightState(ushort mask)
        {
            Sunny.UI.UILightState led_state;
            bool on = Tools.GetBitState(measureSystem.PLC.Device.Info.ButtonInfo, mask);
            led_state = on ? Sunny.UI.UILightState.On : Sunny.UI.UILightState.Off;
            return led_state;
        }

        private Sunny.UI.UILightState GetLedLightState(ushort mask)
        {
            Sunny.UI.UILightState led_state;
            bool on = Tools.GetBitState(measureSystem.PLC.Device.Info.FeedBackInfo, mask);
            led_state = on ? Sunny.UI.UILightState.On : Sunny.UI.UILightState.Off;
            return led_state;
        }

        private Sunny.UI.UILightState GetSafetyLightState(ushort mask, bool reverse = false)
        {
            Sunny.UI.UILightState led_state;
            bool on = Tools.GetBitState(measureSystem.PLC.Device.Info.SafeInfo, mask);
            if (reverse) on = !on;
            led_state = on ? Sunny.UI.UILightState.On : Sunny.UI.UILightState.Off;
            return led_state;
        }

        private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            Properties.Settings.Default.Save();
        }

        private void MenuExitOfflineMode_Click(object sender, EventArgs e)
        {
            Properties.Settings.Default.OfflineMode = false;
            Properties.Settings.Default.Save();
        }

        private void MenuNextStep_Click(object sender, EventArgs e)
        {
            UpdateStep(CurrentStep, 1);
        }

        private void MenuLastStep_Click(object sender, EventArgs e)
        {
            UpdateStep(CurrentStep, -1);
        }

        private void MenuClose_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void MenuSetParams_Click(object sender, EventArgs e)
        {
            formOfflineHanlde.BringToFront();
            formOfflineHanlde.Show();
        }

        private void menuResults_Click(object sender, EventArgs e)
        {
            string current_dir = Directory.GetCurrentDirectory();
            string path_name = Path.Combine(current_dir, "Results\\");
            if (Directory.Exists(path_name))
            {
                Process.Start("explorer", path_name);
            }
        }

        private void menuHistory_Click(object sender, EventArgs e)
        {
            string current_dir = Directory.GetCurrentDirectory();
            string path_name = Path.Combine(current_dir, "..\\..\\Docs\\history\\");
            if (Directory.Exists(path_name))
            {
                Process.Start("explorer", path_name);
            }
        }
    }
}
